package com.huidu.bitrade.service;

import com.huidu.bitrade.constant.CertifiedBusinessStatus;
import com.huidu.bitrade.constant.CommonStatus;
import com.huidu.bitrade.dao.MemberDao;
import com.huidu.bitrade.dao.MemberSignRecordDao;
import com.huidu.bitrade.dao.MemberTransactionDao;
import com.huidu.bitrade.entity.*;
import com.huidu.bitrade.entity.*;
import com.huidu.bitrade.exception.AuthenticationException;
import com.huidu.bitrade.pagination.Criteria;
import com.huidu.bitrade.pagination.PageResult;
import com.huidu.bitrade.pagination.Restrictions;
import com.huidu.bitrade.service.Base.BaseService;
import com.huidu.bitrade.util.BigDecimalUtils;
import com.huidu.bitrade.util.Md5;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.huidu.bitrade.constant.TransactionType.ACTIVITY_AWARD;

@Service
public class MemberService extends BaseService {

    @Autowired
    private MemberDao memberDao;

    @Autowired
    private MemberSignRecordDao signRecordDao;

    @Autowired
    private MemberTransactionDao transactionDao;
    @Autowired
    private LocaleMessageSourceService messageSourceService;
    @Autowired
    private BusinessDepositStrategyService businessDepositStrategyService;

    /**
     * 条件查询对象 pageNo pageSize 同时传时分页
     *
     * @param booleanExpressionList
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Transactional(readOnly = true)
    public PageResult<Member> queryWhereOrPage(List<BooleanExpression> booleanExpressionList, Integer pageNo, Integer pageSize) {
        List<Member> list;
        JPAQuery<Member> jpaQuery = queryFactory.selectFrom(QMember.member)
                .where(booleanExpressionList.toArray(new BooleanExpression[booleanExpressionList.size()]));
        jpaQuery.orderBy(QMember.member.id.desc());
        if (pageNo != null && pageSize != null) {
            list = jpaQuery.offset((pageNo - 1) * pageSize).limit(pageSize).fetch();
        } else {
            list = jpaQuery.fetch();
        }
        return new PageResult<>(list, jpaQuery.fetchCount());
    }

    public Member save(Member member) {
        return memberDao.save(member);
    }

    public Member saveAndFlush(Member member) {
        return memberDao.saveAndFlush(member);
    }

    @Transactional(rollbackFor = Exception.class)
    public Member loginWithToken(String token, String ip, String device) {
        if (StringUtils.isBlank(token)) {
            return null;
        }
        //Member mr = memberDao.findMemberByTokenAndTokenExpireTimeAfter(token,new Date());
        Member mr = memberDao.findMemberByToken(token);
        return mr;
    }

    public Member login(String username, String password) throws Exception {
        Member member = memberDao.findMemberByMobilePhoneOrEmail(username, username);
        if (member == null) {
            throw new AuthenticationException(messageSourceService.getMessage("USER_PASSWORD_ERROR"));
        } else if (!Md5.md5Digest(password + member.getSalt()).toLowerCase().equals(member.getPassword())) {
            throw new AuthenticationException(messageSourceService.getMessage("USER_PASSWORD_ERROR"));
        } else if (member.getStatus().equals(CommonStatus.ILLEGAL)) {
            throw new AuthenticationException(messageSourceService.getMessage("ACCOUNT_ACTIVATION_DISABLED"));
        }
        return member;
    }

    /**
     * @author QQ：97095646
     * @description
     * @date 2019/12/25 18:42
     */
    public Member findOne(Long id) {
        return memberDao.findById(id).orElse(null);
    }

    /**
     * @author QQ：97095646
     * @description 查询所有会员
     * @date 2019/12/25 18:43
     */
    @Override
    public List<Member> findAll() {
        return memberDao.findAll();
    }

    public List<Member> findPromotionMember(Long id) {
        return memberDao.findAllByInviterId(id);
    }

    public Page<Member> findPromotionMemberPage(Integer pageNo, Integer pageSize,Long id){
        Sort orders = Criteria.sortStatic("id");
        PageRequest pageRequest = PageRequest.of(pageNo, pageSize, orders);

        Criteria<Member> specification = new Criteria<Member>();
        specification.add(Restrictions.eq("inviterId", id, false));
        return memberDao.findAll(specification, pageRequest);
    }

    /**
     * @author QQ：97095646
     * @description 分页
     * @date 2019/1/12 15:35
     */
    public Page<Member> page(Integer pageNo, Integer pageSize, CommonStatus status) {
        //排序方式 (需要倒序 这样    Criteria.sort("id","createTime.desc") ) //参数实体类为字段名
        Sort orders = Criteria.sortStatic("id");
        //分页参数
        PageRequest pageRequest = PageRequest.of(pageNo, pageSize, orders);
        //查询条件
        Criteria<Member> specification = new Criteria<Member>();
        specification.add(Restrictions.eq("status", status, false));
        return memberDao.findAll(specification, pageRequest);
    }

    public Page<Member> findByPage(Integer pageNo, Integer pageSize) {
        //排序方式 (需要倒序 这样    Criteria.sort("id","createTime.desc") ) //参数实体类为字段名
        Sort orders = Criteria.sortStatic("id");
        //分页参数
        PageRequest pageRequest = PageRequest.of(pageNo, pageSize, orders);
        //查询条件
        Criteria<Member> specification = new Criteria<Member>();
        return memberDao.findAll(specification, pageRequest);
    }

    public boolean emailIsExist(String email) {
        List<Member> list = memberDao.getAllByEmailEquals(email);
        return list.size() > 0 ? true : false;
    }

    public boolean acceptDepositIdIsExist(Long acceptDepositId) {
        BusinessDepositStrategy strategy = businessDepositStrategyService.findById(acceptDepositId);
        return memberDao.existsMemberByBusinessDepositStrategy(strategy);
    }

    public boolean usernameIsExist(String username) {
        return memberDao.getAllByUsernameEquals(username).size() > 0 ? true : false;
    }

    public boolean phoneIsExist(String phone) {
        return memberDao.getAllByMobilePhoneEquals(phone).size() > 0 ? true : false;
    }

    public Member findByUsername(String username) {
        return memberDao.findByUsername(username);
    }

    public Member findByEmail(String email) {
        return memberDao.findMemberByEmail(email);
    }

    public Member findByPhone(String phone) {
        return memberDao.findMemberByMobilePhone(phone);
    }

    public Page<Member> findAll(Predicate predicate, Pageable pageable) {
        return memberDao.findAll(predicate, pageable);
    }
//    public Page<MemberVo> page(MemberScreen screen, PageModel pageModel){
//        QMember member1 = new QMember("member1");
//        QMember inviterMember = new QMember("member2");
//        ArrayList<Predicate> predicates = new ArrayList<>();
//        if (Objects.nonNull(screen.getStatus())) {
//            predicates.add(member1.certifiedBusinessStatus.eq(screen.getStatus()));
//        }
//        if (Objects.nonNull(screen.getStartTime())) {
//            predicates.add(member1.registrationTime.goe(screen.getStartTime()));
//        }
//        if (Objects.nonNull(screen.getEndTime())) {
//            Calendar calendar = Calendar.getInstance();
//            calendar.setTime(screen.getEndTime());
//            calendar.add(Calendar.DAY_OF_YEAR, 1);
//            predicates.add(member1.registrationTime.lt(calendar.getTime()));
//        }
//        if (StringUtils.isNotEmpty(screen.getAccount())) {
//            predicates.add(member1.username.like("%" + screen.getAccount() + "%")
//                    .or(member1.mobilePhone.like(screen.getAccount() + "%"))
//                    .or(member1.email.like(screen.getAccount() + "%"))
//                    .or(member1.id.like(screen.getAccount()))
//                    .or(member1.realName.like("%" + screen.getAccount() + "%")));
//        }
//        if (Objects.nonNull(screen.getCommonStatus())) {
//            predicates.add(member1.status.eq(screen.getCommonStatus()));
//        }
//        if(org.apache.commons.lang3.StringUtils.isNotEmpty(screen.getSuperPartner())) {
//            predicates.add(member1.superPartner.eq(screen.getSuperPartner()));
//        }
//        JPAQuery<MemberVo> query = queryFactory.select(Projections.fields(MemberVo.class,
//                member1.mobilePhone,member1.id,member1.alipay,member1.email,
//                member1.username,member1.appealSuccessTimes,
//                member1.appealTimes,member1.applicationTime,
//                member1.avatar,member1.bankInfo,
//                member1.buyCsNum,member1.certifiedBusinessApplyTime,
//                member1.certifiedBusinessCheckTime,member1.certifiedBusinessStatus,
//                member1.country,member1.csLevel,member1.firstLevel,member1.wechatPay,
//                member1.transactionStatus,member1.transactions,member1.tokenExpireTime,
//                member1.thirdLevel,member1.superPartner,member1.status,member1.signInAbility,
//                member1.secondLevel,member1.salt,member1.registrationTime,member1.realNameStatus,
//                member1.publishAdvertise,member1.promotionCode,member1.password,member1.memberStarCount,
//                member1.memberLevel,member1.margin,member1.loginCount,member1.location,member1.inviterId,
//                        inviterMember.mobilePhone.as("inviterPhone"))).from(member1,inviterMember).on(inviterMember.id.eq(member1.inviterId))
//                .where(predicates.toArray(new BooleanExpression[predicates.size()])).orderBy(new OrderSpecifier<>(Order.DESC, member1.registrationTime));
//        long total = query.fetchCount() ;
//        query.offset(pageModel.getPageSize()*(pageModel.getPageNo()-1)).limit(pageModel.getPageSize());
//        List<MemberVo> list = query.fetch() ;
//        return new PageImpl<MemberVo>(list,pageModel.getPageable(),total);
//    }


    public String findUserNameById(long id) {
        return memberDao.findUserNameById(id);
    }

    //签到事件
    @Transactional(rollbackFor = Exception.class)
    public void signInIncident(Member member, MemberWallet memberWallet, Sign sign) {
        member.setSignInAbility(false);//失去签到能力
        memberWallet.setBalance(BigDecimalUtils.add(memberWallet.getBalance(), sign.getAmount()));//签到收益

        // 签到记录
        signRecordDao.save(new MemberSignRecord(member, sign));
        //账单明细
        MemberTransaction memberTransaction = new MemberTransaction();
        memberTransaction.setMemberId(member.getId());
        memberTransaction.setAmount(sign.getAmount());
        memberTransaction.setType(ACTIVITY_AWARD);
        memberTransaction.setSymbol(sign.getCoin().getUnit());
        transactionDao.save(memberTransaction);
    }

    //重置会员签到
    public void resetSignIn() {
        memberDao.resetSignIn();
    }

    public void updateCertifiedBusinessStatusByIdList(List<Long> idList) {
        memberDao.updateCertifiedBusinessStatusByIdList(idList, CertifiedBusinessStatus.DEPOSIT_LESS);
    }

    /**
     * 判断验证码是否存在
     * @param promotion
     * @return
     */
    public boolean userPromotionCodeIsExist(String promotion) {
        return memberDao.getAllByPromotionCodeEquals(promotion).size() > 0 ? true : false;
    }

    public Long getMaxId() {
    	return memberDao.getMaxId();
    }

	public Member findMemberByPromotionCode(String code) {
		return memberDao.findMemberByPromotionCode(code);
	}

    public List<Member> findSuperPartnerMembersByIds(String uppers) {
        String[] idss = uppers.split(",");
        List<Long> ids = new ArrayList<>();
        for(String id:idss){
            ids.add(Long.parseLong(id));
        }
        return memberDao.findSuperPartnerMembersByIds(ids);
    }
    public List<Member> findAllByIds(String uppers) {
        String[] idss = uppers.split(",");
        List<Long> ids = new ArrayList<>();
        for(String id:idss){
            ids.add(Long.parseLong(id));
        }
        return memberDao.findAllByIds(ids);
    }

    /**
     * 更新创世股东项目认购累计数量及等级
     * @param member
     * @param number
     */
    public void updateBuyCsNumCsLevel(Member member,int number){
     int buyCsNum=   member.getBuyCsNum()+number;
        member.setBuyCsNum(buyCsNum);
        int csLevel=0;
//        累计购买1个，成为一星创世股东
//        累计购买2个，成为二星创世股东
//        累计购买4个，成为三星创世股东
//        累计购买6个，成为四星创世股东
//        累计购买10个，成为总监创世股东
//        累计购买20个，成为总裁创世股东
//        累计购买40个，成为董事创世股东
        if (buyCsNum < 1) {
            csLevel=0;
        } else if (buyCsNum < 2) {
            csLevel=1;
        } else if (buyCsNum < 4) {
            csLevel=2;
        } else if (buyCsNum < 6) {
            csLevel=3;
        } else if (buyCsNum < 10) {
            csLevel=4;
        } else if (buyCsNum < 20) {
            csLevel=5;
        } else if (buyCsNum < 40) {
            csLevel=6;
        } else {
            csLevel=7;
        }
        member.setCsLevel(csLevel);
    }

    public List<Member> exportMember(String startTime,String endTime){
        List<Member> result = new ArrayList<>();
        List<Member> list;
        Long id = null;
        do {
            list = memberDao.selectMemberExport(startTime,endTime,id);
            if (CollectionUtils.isNotEmpty(list)){
                id = list.get(list.size()-1).getId();
                result.addAll(list);
            }
        }while (CollectionUtils.isNotEmpty(list));
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateInviterId(Long id,Long inviterId) {
         memberDao.updateInviterId(id,inviterId);
    }

}
